using System;
using System.Collections.Generic;
using UnityEngine;
using Framework.Event;

namespace Framework.Manager
{
    public class EventManager : ManagerBase<EventManager>
    {
        #region Manager通用
        private EventManager() { }
        #endregion

        private Dictionary<string, EventContainer> mEventDictionary = new Dictionary<string, EventContainer>();

        /// <summary>每帧发送消息最大数量</summary>
        private const int mSendEventMax = 10;
        private LinkedList<EventUtil> mSendLinkedList = new LinkedList<EventUtil>();
        /// <summary>用于快速查找</summary>
        private HashSet<EventUtil> mEventUtilHashSet = new HashSet<EventUtil>();

        /// <summary>注册事件</summary>
        /// <param name="pEventKey">事件Key</param>
        /// <param name="pEventHandler"></param>
        /// <param name="pPriority">优先级</param>
        public void RegisterEvent(string pEventKey, EventHandler pEventHandler, EnEventPriority pPriority = EnEventPriority.Medium)
        {
            if (string.IsNullOrEmpty(pEventKey))
                throw new ArgumentException("Event key cannot be null or empty", nameof(pEventKey));

            if (pEventHandler == null)
                throw new ArgumentNullException(nameof(pEventHandler));

            EventContainer eventContainer = null;
            if (!mEventDictionary.TryGetValue(pEventKey, out eventContainer))
            {
                eventContainer = new EventContainer(pEventKey);
                mEventDictionary.Add(pEventKey, eventContainer);
            }

            if (!eventContainer.Contains(pEventHandler))
            {
                eventContainer.Add(pEventKey, pEventHandler, pPriority);
            }
            else
            {
                Debug.LogWarning($"Multiple registration, EventKey <color=yellow>{pEventKey}</color> have already registered " +
                                 $"class <color=yellow>{pEventHandler.Target}</color> function <color=yellow>{pEventHandler.Method.Name}</color>.");
            }
        }

        /// <summary>注销事件</summary>
        /// <param name="pEventKey">事件Key</param>
        /// <param name="pEventHandler"></param>
        /// <returns>是否注销成功</returns>
        public bool UnregisterEvent(string pEventKey, EventHandler pEventHandler)
        {
            if (pEventHandler == null) return false;

            EventContainer eventContainer = null;
            if (mEventDictionary.TryGetValue(pEventKey, out eventContainer))
            {
                bool removed = eventContainer.Remove(pEventHandler);
                return removed;
            }

            return false;
        }

        /// <summary>发送事件</summary>
        /// <param name="pEventKey">事件Key</param>
        /// <param name="pEventArgs">事件参数</param>
        public void SendEvent(string pEventKey, EventArgs pEventArgs = null)
        {
            if (string.IsNullOrEmpty(pEventKey)) return;

            EventContainer eventContainer = null;
            if (mEventDictionary.TryGetValue(pEventKey, out eventContainer))
            {
                LinkedList<EventUtil> eventUtilLinkedList = eventContainer.GetEventUtilLinkedList();
                foreach (EventUtil eventUtil in eventUtilLinkedList)
                {
                    if (mEventUtilHashSet.Add(eventUtil))
                    {
                        eventUtil.SetEventArgs(pEventArgs);
                        InsertSendLinkedList(eventUtil);
                    }
                }
            }
        }

        /// <summary>插入发送链表</summary>
        /// <param name="pEventUtil">事件组件</param>
        private void InsertSendLinkedList(EventUtil pEventUtil)
        {
            if (mSendLinkedList.Count <= 0)
            {
                mSendLinkedList.AddFirst(pEventUtil);
                return;
            }

            LinkedListNode<EventUtil> currentNode = mSendLinkedList.First;
            while (currentNode != null)
            {
                if (pEventUtil.Priority < currentNode.Value.Priority)
                {
                    mSendLinkedList.AddBefore(currentNode, pEventUtil);
                    return;
                }

                currentNode = currentNode.Next;
            }

            mSendLinkedList.AddLast(pEventUtil);
        }

        private void Update()
        {
            ProcessEventsPerFrame();
        }

        private void ProcessEventsPerFrame()
        {
            if (mSendLinkedList.Count == 0) return;

            int processedCount = 0;
            while (processedCount < mSendEventMax && mSendLinkedList.Count > 0)
            {
                LinkedListNode<EventUtil> firstNode = mSendLinkedList.First;
                if (firstNode != null)
                {
                    EventUtil eventUtil = firstNode.Value;
                    try
                    {
                        eventUtil.Send();
                    }
                    catch (Exception ex)
                    {
                        Debug.LogError($"Event execution failed: {eventUtil.EventKey}, Error: {ex.Message}");
                    }

                    mSendLinkedList.RemoveFirst();
                    mEventUtilHashSet.Remove(eventUtil);

                    processedCount++;
                }
                else
                {
                    break;
                }
            }
        }

        /// <summary>清除空容器</summary>
        public void ClearEmptyContainers()
        {
            var keysToRemove = new List<string>();

            foreach (KeyValuePair<string, EventContainer> kvp in mEventDictionary)
            {
                if (kvp.Value.Count == 0)
                {
                    kvp.Value.Dispose();
                    keysToRemove.Add(kvp.Key);
                }
            }

            foreach (var key in keysToRemove)
            {
                mEventDictionary.Remove(key);
            }

            Debug.Log($"Cleaned up {keysToRemove.Count} empty event containers");
        }

        /// <summary>清除发送链表</summary>
        public void ClearSendLinkedList()
        {
            mSendLinkedList.Clear();
            mEventUtilHashSet.Clear();
        }

        /// <summary>清除所有事件</summary>
        public void ClearAllEvent()
        {
            ClearSendLinkedList();

            foreach (KeyValuePair<string, EventContainer> kvp in mEventDictionary)
            {
                kvp.Value.Dispose();
            }
            mEventDictionary.Clear();
        }
    }
}